package com.touringapp.android.utils.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONException;

import com.touringapp.android.utils.Logger;
import com.touringapp.android.utils.constants.Constants;

import android.util.Log;

public final class HttpUtil {
    private static final int POST_CONNECTION_TIMEOUT = 10 * 1000;
    private static final int POST_RESPONSE_TIMEOUT = 30 * 1000;
    

    private static BasicHttpParams POST_PARAMS = new BasicHttpParams();
    static {
    	HttpConnectionParams.setConnectionTimeout(POST_PARAMS, POST_CONNECTION_TIMEOUT);
    	HttpConnectionParams.setSoTimeout(POST_PARAMS, POST_RESPONSE_TIMEOUT);
    	HttpConnectionParams.setSocketBufferSize(POST_PARAMS, 8192);
    }

	private static String getRequestUrl(final HttpRequestBase method) throws MalformedURLException {
		return method.getURI().toURL().toString();
	}

	public static final HttpResponse executePost(final String url, final Map<String, Object> params)
    throws com.touringapp.android.utils.http.HttpException,
    		HttpException, JSONException {
    	
        final DefaultHttpClient client = new DefaultHttpClient(POST_PARAMS);
        HttpPost post = new HttpPost(url);
        if (Log.isLoggable(Constants.LOG_TAG_REQUEST, Log.VERBOSE)){
        	logRequest(post, params);
        }
        
        List<NameValuePair> parameters = null;
        if (params != null) {
            parameters = new ArrayList<NameValuePair>();
	        for (Map.Entry<String, Object> paramEntry : params.entrySet()) {
	            String paramName = paramEntry.getKey();
	            Object paramValue = paramEntry.getValue();
	            
	            if ((paramValue instanceof Collection<?>)) {
	                for (Object paramInCollection : (Collection<?>) paramValue) {
	                    addStringParameter(paramName, (String) paramInCollection, parameters);
	                }
	            } else {
	                addStringParameter(paramName, paramValue.toString(), parameters);
	            }
	        }
        }

    	if (params != null) {
        	try {
				post.setEntity(new UrlEncodedFormEntity(parameters, Constants.CHAR_ENCODING_UTF8));
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
    	}
        try {
    		return new ApacheHttpResponseImpl(getRequestUrl(post), client.execute(post));
        } catch (IOException ie) {
            throw new com.touringapp.android.utils.http.HttpException(ie);
        }
    }

	private static void logRequest(final HttpRequestBase request, final Map<String, Object> params) {
		if (!Log.isLoggable(Constants.LOG_TAG_REQUEST, Log.VERBOSE)){
			return;
		}
		if (params != null){
			Log.v(Constants.LOG_TAG_REQUEST, Logger.buildString(" ",
					Constants.LOG_TAG_REQUEST,
					"Request URL:", request.getURI().toString(), params));
		} else {
		Log.v(Constants.LOG_TAG_REQUEST, Logger.buildString(" ",
				Constants.LOG_TAG_REQUEST,
					"Request URL:", request.getURI().toString()));
		}
	}

    private static void addStringParameter(final String paramName, final String value, final List<NameValuePair> parameters) {
        parameters.add(new BasicNameValuePair(paramName, value));
    }
}
